﻿/*
SkyFire 2016-04-28
*/

#ifndef THREAD_POOL_H_
#define THREAD_POOL_H_
#include <thread>
#include <condition_variable>
#include <mutex>
class ThreadPool {
private:
    size_t maxRunSize;													//最大允许运行线程数量
    size_t currSize;													//当前运行线程数量
    std::mutex mu;														//currSize锁
    std::mutex mu2;														//waitNum锁
    std::mutex mu3;														//条件变量锁
    std::mutex mu4;														//maxRunSize锁
    size_t waitNum;														//等待中的线程数量
    std::condition_variable cond;										//条件变量
public:
    void setMaxRunSize(int);											//设置最多运行数量
    ThreadPool(int maxRunSize_t);										//参数为同时可运行的最多线程数量
    template<typename U, typename...T>
    bool addThread(U(*func)(T...), T...args);							//带参数的线程加入,如果线程函数参数不等于传入的实际参数，返回false，否则返回0
    template<typename U>
    void addThread(U(*func)());											//无参的线程加入
};

template<typename U, typename...T>
inline bool ThreadPool::addThread(U(*func)(T...), T...args) {           //func：函数指针   args：给func传递的参数
    std::thread([=]()->void {                                           //启动一个新线程
        mu.lock();
        mu4.lock();
        if(currSize < maxRunSize) {                                     //如果当前运行的线程小于指定的最大线程数量
            mu4.unlock();
            mu.unlock();
        } else {                                                        //如果当前运行的线程大于等于指定的最大线程数量，增加一个等待线程数量，让线程休眠，等待被唤醒
            mu4.unlock();
            mu.unlock();
            mu2.lock();
            ++waitNum;
            mu2.unlock();
            std::unique_lock<std::mutex> lk{ mu3 };
            cond.wait(lk);
        }
        mu.lock();
        currSize++;                                                     //线程唤醒后运行或者直接可以运行时，增加正在运行的线程数量，并开始执行func函数
        mu.unlock();
        func(args...);                                                  //执行func函数
        mu.lock();
        --currSize;                                                     //执行完毕后，减少正在运行的数量
        mu.unlock();
        mu2.lock();
        if(waitNum > 0) {                                               //如果有在等待的线程，唤醒一个
            std::lock_guard<std::mutex> lk{ mu3 };
            --waitNum;                                                  //唤醒后，等待的线程减一
            cond.notify_one();
        }
        mu2.unlock();
    }).detach();
    return true;
}
template<typename U>
inline void ThreadPool::addThread(U(*func)()) {
    std::thread([=]()->void {
        mu.lock();
        mu4.lock();
        if(currSize < maxRunSize) {
            mu4.unlock();
            mu.unlock();
        } else {
            mu4.unlock();
            mu.unlock();
            mu2.lock();
            ++waitNum;
            mu2.unlock();
            std::unique_lock<std::mutex> lk{ mu3 };
            cond.wait(lk);
        }
        mu.lock();
        currSize++;
        mu.unlock();
        func();
        mu.lock();
        --currSize;
        mu.unlock();
        mu2.lock();
        if(waitNum > 0) {
            std::lock_guard<std::mutex> lk{ mu3 };
            --waitNum;
            cond.notify_one();
        }
        mu2.unlock();
    }).detach();
}
#endif
